﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices.ComTypes;

namespace Tsanie.ShellExtension {

    public abstract class DropHandlerBase : IDropTarget, IPersistFile {

        #region - 私有变量 -

        private string m_TargetFilename;
        private FileCollection m_DraggedFiles;

        #endregion

        #region - 构造 -

        protected DropHandlerBase() : base() { }

        #endregion

        #region - 公共属性 -

        /// <summary>
        /// 获得目标文件名
        /// </summary>
        public string Filename {
            get {
                return m_TargetFilename;
            }
        }

        /// <summary>
        /// 获得拖拽的文件名集合
        /// </summary>
        public FileCollection Files {
            get {
                return m_DraggedFiles;
            }
        }

        #endregion

        #region - 公共方法 -

        /// <summary>
        /// Notifies when a drag-and-drop operation is completed.
        /// </summary>
        /// <param name="KeyState">Current state of ALT, CTRL and SHIFT keys</param>
        /// <param name="X">The x-coordinate of the mouse pointer, in screen coordinates</param>
        /// <param name="Y">The y-coordinate of the mouse pointer, in screen coordinates</param>
        /// <param name="Effect">The target drop effect</param>
        /// <returns>The accepted drop effects.</returns>
        public virtual DragDropEffects OnDragDrop(KeyStates keyState, int x, int y, DragDropEffects effect) {
            return DragDropEffects.None;
        }

        /// <summary>
        /// Indicates whether a drop can be accepted, and, if so, the effect of the drop.
        /// </summary>
        /// <param name="KeyState">Current state of ALT, CTRL and SHIFT keys</param>
        /// <param name="X">The x-coordinate of the mouse pointer, in screen coordinates</param>
        /// <param name="Y">The y-coordinate of the mouse pointer, in screen coordinates</param>
        /// <param name="Effect">The target drop effect</param>
        /// <returns>The accepted drop effects.</returns>
        public virtual DragDropEffects OnDragEnter(KeyStates keyState, int x, int y, DragDropEffects effect) {
            return DragDropEffects.Move;
        }

        /// <summary>
        /// Notifies that the operation ended without dropping the files.
        /// </summary>
        public virtual void OnDragLeave() { }

        /// <summary>
        /// Provides target feedback to the user.
        /// </summary>
        /// <param name="KeyState">Current state of ALT, CTRL and SHIFT keys</param>
        /// <param name="X">The x-coordinate of the mouse pointer, in screen coordinates</param>
        /// <param name="Y">The y-coordinate of the mouse pointer, in screen coordinates</param>
        /// <param name="Effect">The target drop effect</param>
        /// <returns>The accepted drop effects.</returns>
        public virtual DragDropEffects OnDragOver(KeyStates keyState, int x, int y, DragDropEffects effect) {
            return DragDropEffects.Move;
        }

        #endregion

        #region - IPersistFile 成员 -

        void IPersistFile.GetClassID(out Guid pClassID) { pClassID = Guid.Empty; }
        void IPersistFile.GetCurFile(out string ppszFileName) { ppszFileName = string.Empty; }
        int IPersistFile.IsDirty() { return 0; }
        void IPersistFile.Load(string pszFileName, int dwMode) { m_TargetFilename = pszFileName; }
        void IPersistFile.Save(string pszFileName, bool fRemember) { }
        void IPersistFile.SaveCompleted(string pszFileName) { }

        #endregion

        #region - IDropTarget 成员 -

        void IDropTarget.DragEnter(IDataObject pDataObj, KeyStates grfKeyState, int ptX, int ptY, ref DragDropEffects pdwEffect) {
            // Get the dragged files
            m_DraggedFiles = new FileCollection(pDataObj);
            pdwEffect = OnDragEnter(grfKeyState, ptX, ptY, pdwEffect);
        }

        void IDropTarget.DragOver(KeyStates grfKeyState, int ptX, int ptY, ref DragDropEffects pdwEffect) {
            pdwEffect = OnDragOver(grfKeyState, ptX, ptY, pdwEffect);
        }

        void IDropTarget.DragLeave() {
            OnDragLeave();
            Clean();
        }

        void IDropTarget.Drop(IDataObject pDataObj, KeyStates grfKeyState, int ptX, int ptY, ref DragDropEffects pdwEffect) {
            pdwEffect = OnDragDrop(grfKeyState, ptX, ptY, pdwEffect);
            Clean();
        }

        #endregion

        private void Clean() {
            // Clear the dragged files 
            m_DraggedFiles.Dispose();
            m_DraggedFiles = null;
        }

        #region - COM 注册 -

        [System.Runtime.InteropServices.ComRegisterFunction()]
        private static void ComReg(Type t) {
            // Register the extension
            Common.RegisterExtension(t, "DropHandler");
        }

        [System.Runtime.InteropServices.ComUnregisterFunction()]
        private static void ComUnreg(Type t) {
            // Unregister the extension
            Common.UnregisterExtension(t, "DropHandler");
        }

        #endregion

    }
}
